package com.expert.service.Impl;

import com.expert.Mapper.UserMapper;
import com.expert.constant.JwtClaimConstant;
import com.expert.constant.RedisKeyConstant;
import com.expert.dto.RefreshTokenDTO;
import com.expert.exception.RefreshTokenException;
import com.expert.pojo.User;
import com.expert.properties.JwtProperties;
import com.expert.service.RefreshTokenService;
import com.expert.util.JwtUtil;
import com.expert.vo.RefreshTokenVo;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: RefreshTokenServiceImpl
 * @Author: cxs
 * @Date: 2024/01/19 15:30
 * @Description:
 **/
@Service
@Slf4j
public class RefreshTokenServiceImpl implements RefreshTokenService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    JwtProperties jwtProperties;
    @Autowired
    UserMapper userMapper;
    /**
     * 刷新token
     * @param refreshTokenDTO
     * @return
     */
    @Override
    public RefreshTokenVo refresh(RefreshTokenDTO refreshTokenDTO) {
        //在redis中获取token
        String dbToken = (String) redisTemplate.opsForValue().get(RedisKeyConstant.REFRESH_TOKEN+refreshTokenDTO.getUserAccount());
        if (refreshTokenDTO.getRefreshToken()==null||dbToken==null){
            log.info("token为空");
            throw new RefreshTokenException("token为空");
        }
        log.info(dbToken);
        log.info(refreshTokenDTO.getRefreshToken());
        //校验token是否相同
        if (!refreshTokenDTO.getRefreshToken().equals(dbToken)){
            log.info("token不匹配");
            throw new RefreshTokenException("token不匹配");
        }
        //校验token是否属于该用户
        String refreshToken = refreshTokenDTO.getRefreshToken();
        Claims claims = JwtUtil.parseJWT(jwtProperties.getRefreshSecretKey(), refreshToken);
        Long id = Long.valueOf(claims.get(JwtClaimConstant.USER_ID).toString());
        User user = userMapper.selectById(id);
        if (user ==null||!refreshTokenDTO.getUserAccount().equals(user.getAccount())) {
            log.info("用户不匹配");
            throw new RefreshTokenException("用户不匹配");
        }
        //校验通过，重新生成Token
        //生成令牌
        Map<String, Object> newClaims = new HashMap<>();
        claims.put(JwtClaimConstant.USER_ID, user.getId());
        String accessToken = JwtUtil.createJWT(jwtProperties.getAccessSecretKey(), jwtProperties.getAccessTtl(), claims);
       log.info(accessToken+" "+accessToken);
        String newRefreshToken = JwtUtil.createJWT(jwtProperties.getRefreshSecretKey(), jwtProperties.getRefreshTtl(), claims);
        //将refreshToken存入redis
        redisTemplate.opsForValue().set(
                RedisKeyConstant.REFRESH_TOKEN + user.getAccount(),
                newRefreshToken, jwtProperties.getRefreshTtl(), TimeUnit.MILLISECONDS
        );
        //封装VO
        RefreshTokenVo refreshTokenVo = RefreshTokenVo.builder()
                .accessToken(accessToken)
                .refreshToken(newRefreshToken).build();
        return refreshTokenVo;
    }
}
